package io.nads.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import io.nads.api.impl.QiniuTTS;
import io.nads.api.impl.QiniuUploader;
import io.nads.config.QiniuConfig;
import io.nads.constant.RedisConstant;
import io.nads.context.BaseContext;
import io.nads.entity.UserChatMessage;
import io.nads.service.ITTSService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
@Slf4j
public class TTSServiceImpl implements ITTSService {

    private final QiniuTTS qiniuTTS;
    private final StringRedisTemplate stringRedisTemplate;
    private final QiniuConfig qiniuConfig;
    private final QiniuUploader qiniuUploader;

    private static final String VOICE_REDIS_KEY = RedisConstant.QINIU_TTS_VOICE_KEY;

    /**
     * 从Redis获取支持的音色列表
     *
     * @return 音色列表，如果缓存中没有则返回空列表
     */
    private List<String> getSupportedVoicesFromRedis() {
        String jsonStr = stringRedisTemplate.opsForValue().get(VOICE_REDIS_KEY);
        if (StrUtil.isEmpty(jsonStr)) {
            return Collections.emptyList();
        }
        log.info("从redis读取到了所有支持的音色{}", jsonStr);
        return JSONUtil.toList(jsonStr, String.class);
    }

    /**
     * 将支持的音色列表保存到Redis
     *
     * @param supportedVoices 音色列表
     */
    private void saveSupportedVoices2Redis(List<String> supportedVoices) {
        String jsonStr = JSONUtil.toJsonStr(supportedVoices);
        long expireSeconds = qiniuConfig.getTts().getVoiceRedisExpireSeconds();
        stringRedisTemplate.opsForValue().set(VOICE_REDIS_KEY, jsonStr, expireSeconds, TimeUnit.SECONDS);
        log.info("缓存支持的音色到redis {}", jsonStr);
    }

    /**
     * 获取某个message的语音
     *
     * @param message
     * @return
     */
    @Override
    public String getVoiceUrl(UserChatMessage message) {
        // 先从redis中获取
        String key = RedisConstant.QINIU_TTS_URL_KEY_PREFIX + message.getId();
        long expireSec = Math.max(qiniuConfig.getTts().getVoiceRedisExpireSeconds() - 5, 1);
        String url = stringRedisTemplate.opsForValue().get(key);
        if (StrUtil.isNotEmpty(url)) {
            return url;
        } else {
            String content = message.getContent();
            if (StrUtil.isEmpty(content)) {
                return null;
            }
            // 从BaseContex获取UserID
            Long userId = BaseContext.getCurrentId();
            // 检查Redis中当前的sessionID是否和当前请求的sessionID一直
            String voiceKey = RedisConstant.CHAT_SESSION_VOICE_KEY_PREFIX + userId;
            String voice = stringRedisTemplate.opsForValue().get(voiceKey);

            if (StrUtil.isEmpty(voice)) {
                voice = getSupportedVoices().getFirst();
            }
            InputStream inputStream = qiniuTTS.textToSpeech(content, voice);
            url = qiniuUploader.upload(inputStream, "tts_" + message.getUserId() + ".mp3");
            stringRedisTemplate.opsForValue().set(key, url, expireSec, TimeUnit.SECONDS);
            return url;
        }
    }

    @Override
    public List<String> getSupportedVoices() {
        // 先从Redis缓存中获取原始数据（带括号）
        List<String> rawVoices = getSupportedVoicesFromRedis();
        if (CollectionUtil.isEmpty(rawVoices)) {
            // 缓存中没有数据，从QiniuTTS获取原始数据
            rawVoices = qiniuTTS.getSupportedVoices();
            if (CollectionUtil.isEmpty(rawVoices)) {
                return Collections.emptyList();
            }
            // 保存原始数据（带括号）到Redis缓存
            saveSupportedVoices2Redis(rawVoices);
        }

        // 处理数据，去掉括号中的音色名称，只返回音色类型
        return rawVoices.stream()
                .map(voice -> voice.contains(" (") ? voice.substring(0, voice.indexOf(" (")) : voice)
                .toList();
    }

    @Override
    public List<String> getSupportedVoiceLabels() {
        // 先从Redis缓存中获取原始数据（带括号）
        List<String> rawVoices = getSupportedVoicesFromRedis();
        if (CollectionUtil.isEmpty(rawVoices)) {
            // 缓存中没有数据，从QiniuTTS获取原始数据
            rawVoices = qiniuTTS.getSupportedVoices();
            if (CollectionUtil.isEmpty(rawVoices)) {
                return Collections.emptyList();
            }
            // 保存原始数据（带括号）到Redis缓存
            saveSupportedVoices2Redis(rawVoices);
        }

        // 提取括号中的音色名称
        return rawVoices.stream()
                .map(voice -> {
                    if (voice.contains(" (") && voice.contains(")")) {
                        int start = voice.indexOf(" (") + 2;
                        int end = voice.lastIndexOf(")");
                        return voice.substring(start, end);
                    }
                    return ""; // 如果没有括号，返回空字符串
                })
                .filter(label -> !label.isEmpty()) // 过滤掉空字符串
                .toList();
    }
}
